#! /usr/bin/env python
#coding:utf-8
#written by guolt;

import sys
import os
import shutil
import logging
import time
from hashlib import md5

"""
squid push and purge files!
xxx.status文件状态说明：
1:正在上传；
2:上传完成；
3:正在分发；
4:分发完成；
5:分发失败；

delete文件列表，需要看detele目录；
purge主机对应的ip为内网，对应的主机名和ip写在hosts文件中；

"""

#定义全局变量；
ftp_dir='/h3/update/download'
ftp_del_dir='/h3/update/download/delete'
cdn_base='/u01/cdnLog'
cdn_log=os.path.join(cdn_base,'check_cdn.log')
cdn_tmp=cdn_base+os.sep+'cdn_tmp'
cdn_host_ip={'idc-cdn1.wuxi.jl':'58.215.80.133','idc-cdn2.wuxi.jl':'58.215.80.134'}
cdn_url="test.grandes.com.cn"
#程序检测间隔；
check_time=10

logging.basicConfig(level=logging.DEBUG,
                format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                datefmt='%a, %d %b %Y %H:%M:%S',
                filename=cdn_log,
                filemode='a')



#################################################################################################
#定义一个StreamHandler，将INFO级别或更高的日志信息打印到标准错误，并将其添加到当前的日志处理对象#
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
#################################################################################################



def getStatus(self):
    """
    获得xxx.status文件的tag,然后做出相应的流程处理；
    """
#切换目录；
    os.chdir(ftp_dir)
#tagfile是以xxx.status结尾的文件；
    try:
        tagfile=open(self,'r')
        tag=tagfile.readline()
        tag=tag.rstrip('\n')
        tagfile.close()
        return tag      #获得tag值;
    except:


def changeStatus(self,status):
    """
    修改文件的状态值.例如：1，2，3，4，5
    """
    status=str(status)
    status_file=open(self,'w')
    status_file.write(status)
    status_file.flush()
    status_file.close()

def getMd5(self):
    """
    获得文件md5值；
    """
    m = md5()
    try:
        a_file = open(self, 'r')
        m.update(a_file.read())
        a_file.close()
        return m.hexdigest()
    except:
#返回错误的md5值;
        return 123
        logging.warning('文件 %s 没有找到！' %self)

def push_file(self):
    """
    推送url到各节点；
    """
    for cdn_host,ip in cdn_host_ip.items():
        cdn_tmp_dir=cdn_tmp+os.sep+cdn_host
        print "cdn_tmp_dir is: ", cdn_tmp_dir
#如果不存在以各节点命名的文件目录，就创建；
        if not os.path.exists(cdn_tmp_dir):
            os.mkdir(cdn_tmp_dir)
            print "create dir done!!!"
#如果目录非空就删除，创建空目录；
        else:
            if len(os.listdir(cdn_tmp_dir)) != 0:
                shutil.rmtree(cdn_tmp_dir)
                os.mkdir(cdn_tmp_dir)
                print "........create...."

#开始分发url....
        os.chdir(cdn_tmp_dir)
        logging.info("准备推送资源到 %s, 推送的资源是: %s " %(cdn_host,self))
        os.system('wget -q -c -t 5 -T 3 --header "host:%s" http://%s/%s' % (cdn_url,ip,self))

        pushfile_tmp=cdn_tmp_dir+os.sep+self
        print "pushfile_tmp: %s" %pushfile_tmp
        md5_pushfile=getMd5(pushfile_tmp)
        logging.info('%s 主机，临时文件%s的md5值为：%s' %(cdn_host,pushfile_tmp,md5_pushfile))

        if getMd5(cdn_tmp_dir+os.sep+self) == self.split('.')[0]:
            changeStatus(ftp_push_status,'4')
            logging.info('推送的资源：%s，经过校验md5值，文件完整' %pushfile_tmp)
        else:
            changeStatus(ftp_push_status,'5')
            logging.warning('推送的资源：%s，经过校验md5值，文件不正确！' %pushfile_tmp)

def purge_file(self):
    """
    purge url资源;
    """
    for cdn_host,ip in cdn_host_ip.items():
        purgeFile=self
        print purgeFile
        print "开始purge %s 主机上的 %s 的 url........." %(cdn_host,purgeFile)
        os.system('/usr/sbin/squidclient -h %s -p 80 -m PURGE http://%s/%s' %(cdn_host,cdn_url,purgeFile))



if __name__ == '__main__':
    while True:
#ftp_push_status 为ftp_dir目录下以.status结尾的tag文件(push文件的tag)；ftp_push_file为推送url;
        for ftp_push_file in os.listdir(ftp_dir):
            os.chdir(ftp_dir)
#ftp_push_file要同时是文件，排除目录的类型，并且不是以xxx.status结尾的文件，才符合要求；
            if os.path.isfile(ftp_push_file) and ftp_push_file.endswith('status') == False:
                print "ftp_push_file is %s" %ftp_push_file
                ftp_push_status=os.path.join(ftp_dir,ftp_push_file.split('.')[0]+'.status')

                if os.path.exists(ftp_push_status) and getStatus(ftp_push_status) == '2':
                    logging.info('%s 文件将推送到每个主机..... ' %ftp_push_file)
#针对一个推送文件，遍历所有主机，进行推送；
                    for cdn_host,ip in cdn_host_ip.items():
                        cdn_tmp_dir=cdn_tmp+os.sep+cdn_host
                        print "cdn_tmp_dir is: ", cdn_tmp_dir
#如果不存在以各节点命名的文件目录，就创建；
                        if not os.path.exists(cdn_tmp_dir):
                            os.mkdir(cdn_tmp_dir)
                            print "create dir done!!!"
#如果目录非空就删除，创建空目录；
                        else:
                            if len(os.listdir(cdn_tmp_dir)) != 0:
                                shutil.rmtree(cdn_tmp_dir)
                                os.mkdir(cdn_tmp_dir)
                                print "........create...."

#将tag置于“正在分发”状态；
                        changeStatus(ftp_push_status,'3')
#开始分发资源
                        push_file(ftp_push_file)
                        print "分发完成。。"
                elif os.path.exists(ftp_push_status) and getStatus(ftp_push_status) == '3':
                    print "正在分发。。。"
                    changeStatus(ftp_push_status,'3')
#status文件状态为3，执行purge后，在push 该url;
#                   logging.INFO('文件 %s 状态为分发失败，先 purge，在push资源.' %ftp_push_file)
                    purge_file(ftp_push_file)
                    push_file(ftp_push_file)
#执行purge后，在push 该url，然后将status文件状态为4，
                    changeStatus(ftp_push_status,'4')


#    print "跳过刷新模块！"
#    logging.info("#"*40)
#    exit()

        if os.path.isdir(ftp_del_dir):
            for f_del in os.listdir(ftp_del_dir):
                f_del_ok=os.path.join(ftp_del_dir,f_del.split('.')[0] + '.ok')
#查找目录下有没有f_del对应的f_del_ok文件，没有就代表文件没有purge,如果有，就代表purge完成了.
                if not os.path.exists(f_del.split('.')[0]+'.ok'):
                    purge_file(f_del)
                    logging.info('成功puege %s' %f_del)
                    f_del_ok_create=open(f_del_ok,'w')
                    f_del_ok_create.close()

        print "@"*30
        time.sleep(check_time)








